package cn.edu.ustc.multicore.exercise.ch5;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;

public class ImplicitSimpleReadWriteLock implements ReadWriteLock {
	int readers;
	boolean writer;
	Lock readLock, writeLock;

	public ImplicitSimpleReadWriteLock() {
		writer = false;
		readers = 0;
		readLock = new ReadLock();
		writeLock = new WriteLock();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.util.concurrent.locks.ReadWriteLock#readLock()
	 */
	public Lock readLock() {
		return this.readLock;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.util.concurrent.locks.ReadWriteLock#writeLock()
	 */
	public Lock writeLock() {
		return this.writeLock;
	}

	private class ReadLock implements Lock {

		public void lock() {
			synchronized (this) {
				try {
					while (writer) {
						wait();
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				readers++;
			}
		}

		public void unlock() {
			synchronized (this) {
				readers--;
				if (readers == 0)
					notifyAll();
			}
		}

		public void lockInterruptibly() throws InterruptedException {
			// TODO Auto-generated method stub

		}

		public Condition newCondition() {
			// TODO Auto-generated method stub
			return null;
		}

		public boolean tryLock() {
			// TODO Auto-generated method stub
			return false;
		}

		public boolean tryLock(long time, TimeUnit unit)
				throws InterruptedException {
			// TODO Auto-generated method stub
			return false;
		}
	}

	private class WriteLock implements Lock {

		public void lock() {
			synchronized (this) {
				try {
					while (readers > 0) {
						wait();
					}
					writer = true;
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}

		public void unlock() {
			synchronized(this){
				writer = false;
				notifyAll();
			}
		}

		public void lockInterruptibly() throws InterruptedException {

		}

		public Condition newCondition() {
			// TODO Auto-generated method stub
			return null;
		}

		public boolean tryLock() {
			// TODO Auto-generated method stub
			return false;
		}

		public boolean tryLock(long time, TimeUnit unit)
				throws InterruptedException {
			// TODO Auto-generated method stub
			return false;
		}

	}
}
